package br.unicamp.ic.sgct.server.dominio.entidades;

//import it.biobytes.ammentos.AutomaticType;
//import it.biobytes.ammentos.FieldTypeEnum;
//import it.biobytes.ammentos.PersistentEntity;
//import it.biobytes.ammentos.PersistentField;
//import it.biobytes.ammentos.PersistentList;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import br.unicamp.ic.sgct.client.dominio.to.AreaTO;
import br.unicamp.ic.sgct.client.dominio.to.ConferenciaTO;
import br.unicamp.ic.sgct.client.dominio.to.SessaoTO;
import br.unicamp.ic.sgct.client.dominio.to.TrabalhoTO;
import br.unicamp.ic.sgct.client.dominio.to.UsuarioTO;
import br.unicamp.ic.sgct.server.recursos.persistencia.LOGGER;


@SuppressWarnings("serial")
//@PersistentEntity(sourceDomain = "T_CONFERENCIA", primaryKey = "id_conf")
@Entity(name="Conferencia")
@Table(name="T_CONFERENCIA")
@TableGenerator(name = "CONFERENCIA_GEN", allocationSize = 1, initialValue = 1, table = "T_ID", 
		pkColumnName = "key", valueColumnName = "valor", pkColumnValue = "ID_CONF")
@NamedQueries({
    @NamedQuery(name = "Conferencia.findByTerminoMaiorIgualCurrentDate", 
    		query = "SELECT  entity  FROM Conferencia entity where  entity.termino >= current_date()"),
    @NamedQuery(name = "Conferencia.findByTerminoChamadaTrabalhosMaiorIgualCurrentDate", 
    		query = "SELECT  entity  FROM Conferencia entity where  entity.terminoChamadaTrabalhos >= current_date()")
})		
public class Conferencia implements Serializable {
	//public static final String PERSISTENCE_DOMAIN = "T_CONFERENCIA";
	public static final String findByTerminoMaiorIgualCurrentDate = "Conferencia.findByTerminoMaiorIgualCurrentDate";
	public static final String findByTerminoChamadaTrabalhosMaiorIgualCurrentDate = "Conferencia.findByTerminoChamadaTrabalhosMaiorIgualCurrentDate";
	//@PersistentField(fieldName="id_conf", automatic=true, automaticType=AutomaticType.FRAMEWORK)
	@Id
	@Column(name="id_conf")
	@GeneratedValue(strategy = GenerationType.TABLE, generator = "CONFERENCIA_GEN")
	private long id;

	//@PersistentField(size="20")
	@Column(length=20, nullable=false)
	private String titulo;
	
	//@PersistentField(size="150")
	@Column(length=159)	
	private String descricao;

	//@PersistentField(type=FieldTypeEnum.DATE)
	@Column(nullable=false)	
	@Temporal(value = TemporalType.DATE)
	private Date inicio;

	//@PersistentField(type=FieldTypeEnum.DATE)
	@Column(nullable=false)	
	@Temporal(value = TemporalType.DATE)
	private Date termino;

	//@PersistentField(size="50")
	@Column(length=50)
	private String endereco;

	//@PersistentField(type=FieldTypeEnum.DATE)
	@Column	
	@Temporal(value = TemporalType.DATE)
	private Date inicioChamadaTrabalhos;
	
	//@PersistentField(type=FieldTypeEnum.DATE)
	@Column	
	@Temporal(value = TemporalType.DATE)
	private Date terminoChamadaTrabalhos;

	//@PersistentField(fieldName="id_cconv", type=FieldTypeEnum.ENTITY)
	@OneToOne(optional = true, targetEntity = CentroConvencao.class, fetch=FetchType.LAZY)
    @JoinColumn(name = "id_cconv", nullable = true)
	private CentroConvencao centroConvencao;

	//@PersistentList(query = "id_conf=?", cascadeOnSave = true, cascadeOnDelete = false, deleteOnRemove = false)
    @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY, mappedBy = "conferencia")	
	private List<Sessao> sessoesConferencia;

    
    @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY, mappedBy = "conferencia")
    private Set<Trabalho> trabalhos;
    
    @OneToMany(fetch = FetchType.LAZY, targetEntity = Usuario.class, mappedBy="conferencia")
    private Set<Usuario> usuarios;
    
    @ManyToMany(fetch = FetchType.EAGER, targetEntity = Area.class)
    @JoinTable(name = "T_CONFERENCIA_AREA",
        joinColumns = @JoinColumn(name = "CONF_ID", referencedColumnName = "ID_CONF"),
        inverseJoinColumns = @JoinColumn(name = "AREA_ID", referencedColumnName = "ID_AREA")
    )
    private Set<Area> areas;
    
    
	public Conferencia() {
		super();
	}

	/**
	 * 
	 * @param titulo
	 * @param descricao
	 * @param inicio
	 * @param termino
	 * @param endereco
	 * @param inicioChamadaTrabalhos
	 * @param terminoChamadaTrabalhos
	 * @param centro
	 */
	public Conferencia(String titulo, String descricao, Date inicio,
			Date termino, String endereco, Date inicioChamadaTrabalhos,
			Date terminoChamadaTrabalhos, CentroConvencao centro, List<Sessao> sessoes) {
		super();
		this.titulo = titulo;
		this.descricao = descricao;
		this.inicio = inicio;
		this.termino = termino;
		this.endereco = endereco;
		this.inicioChamadaTrabalhos = inicioChamadaTrabalhos;
		this.terminoChamadaTrabalhos = terminoChamadaTrabalhos;
		this.centroConvencao = centro;
		this.sessoesConferencia = sessoes;
	}

	//~ getters & setters
	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getDescricao() {
		return descricao;
	}

	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}

	public Date getInicio() {
		return inicio;
	}

	public void setInicio(Date inicio) {
		this.inicio = inicio;
	}

	public Date getTermino() {
		return termino;
	}

	public void setTermino(Date termino) {
		this.termino = termino;
	}

	public String getEndereco() {
		return endereco;
	}

	public void setEndereco(String endereco) {
		this.endereco = endereco;
	}

	/**
	 * Inicio para submissao do resumo de artigos
	 * 
	 * @return java.util.Date
	 */
	public Date getInicioChamadaTrabalhos() {
		return inicioChamadaTrabalhos;
	}

	public void setInicioChamadaTrabalhos(Date inicioChamadaTrabalhos) {
		this.inicioChamadaTrabalhos = inicioChamadaTrabalhos;
	}

	/**
	 * Termino para submissao do resumo de artigos
	 * 
	 * @return java.util.Date
	 */
	public Date getTerminoChamadaTrabalhos() {
		return terminoChamadaTrabalhos;
	}

	public void setTerminoChamadaTrabalhos(Date terminoChamadaTrabalhos) {
		this.terminoChamadaTrabalhos = terminoChamadaTrabalhos;
	}

	public String getTitulo() {
		return titulo;
	}

	public void setTitulo(String titulo) {
		this.titulo = titulo;
	}

	public CentroConvencao getCentroConvencao() {
		return centroConvencao;
	}

	public void setCentroConvencao(CentroConvencao centroConvencao) {
		this.centroConvencao = centroConvencao;
	}

	public List<Sessao> getSessoesConferencia() {
		return sessoesConferencia;
	}

	public void setSessoesConferencia(List<Sessao> sessoesConferencia) {
		this.sessoesConferencia = sessoesConferencia;
	}


	/**
	 * METODOS DE NEGOCIO
	 * 
	 */
	
    public void adicionar(Trabalho trabalho){
    	this.trabalhos.add(trabalho);
    }
    public void adicionar(Usuario usuario){
    	this.usuarios.add(usuario);
    }
    
    public List<Trabalho> obterTrabalhos(){
    	return new ArrayList<Trabalho>(trabalhos);
    }

    /**
     *  
     * @param id
     * @return 
     */
    public Trabalho obterTrabalho(Long id){
    	Trabalho retorno = null;
    	for (Trabalho trabalho : trabalhos) {
			if(trabalho.getIdTrabalho() == id){
				retorno = trabalho;
				break;
			}
		}
    	return retorno;
    }
    

    public List<Usuario> obterUsuarios(){
    	return new ArrayList<Usuario>(usuarios);
    }
    

	
	/**
	 * Constructs a <code>String</code> with all attributes
	 * in name = value format.
	 *
	 * @return a <code>String</code> representation 
	 * of this object.
	 */
	public String toString()
	{
	    final String TAB = "    ";
	    
	    String retValue = "";
	    
	    retValue = "Conferencia ( "
	        + super.toString() + TAB
	        + "id = " + this.id + TAB
	        + "titulo = " + this.titulo + TAB
	        + "descricao = " + this.descricao + TAB
	        + "inicio = " + this.inicio + TAB
	        + "termino = " + this.termino + TAB
	        + "endereco = " + this.endereco + TAB
	        + "inicioChamadaTrabalhos = " + this.inicioChamadaTrabalhos + TAB
	        + "terminoChamadaTrabalhos = " + this.terminoChamadaTrabalhos + TAB
	        +  "centroConvencao = " + (this.centroConvencao != null ? this.centroConvencao + TAB : "NULL ")
	        + " )";
	
	    return retValue;
	}
	
	/**
	 * 
	 * @param Conferencia
	 * @return ConferenciaTO
	 */
	public ConferenciaTO getTo() throws Exception {
		LOGGER.debug("\nConferencia :: getTo() acionado");

		ConferenciaTO to = new ConferenciaTO();
		to.setDescricao( this.getDescricao() );
		to.setEndereco( this.getEndereco() );
		to.setId( this.getId() );
		to.setInicio( this.getInicio() );
		to.setInicioChamadaTrabalhos( this.getInicioChamadaTrabalhos() );
		to.setTermino( this.getTermino() );
		to.setTerminoChamadaTrabalhos( this.getTerminoChamadaTrabalhos() );
		to.setTitulo( this.getTitulo() );
		//
		to.setCentroConvencao( this.getCentroConvencao().getTo() );
		to.setAreas(new ArrayList<AreaTO>());
		to.setSessoesConferencia( new ArrayList<SessaoTO>() );
		
		
		for (Area area : areas) {
			to.getAreas().add(area.getTo()); 	
		}
		for (Sessao sessao : sessoesConferencia) {
			to.getSessoesConferencia().add(sessao.getTo()); 	
		}
                
		return to;
	}

    /**
     * @return the areas
     */
    public Set<Area> getAreas() {
        return areas;
    }

    /**
     * @param areas the areas to set
     */
    public void setAreas(Set<Area> areas) {
        this.areas = areas;
    }
}